package com.abc.fast.generator.server;

import com.abc.fast.generator.utils.DbUtil;
import com.abc.fast.generator.utils.Field;
import com.abc.fast.generator.utils.FreemarkerUtil;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.util.*;

public class ServerGenerator {

    static String serverPath = "fast-framework/fast-generator/src/main/java/com/abc/fast/generator/gen/[module]/";
    static String resourcesPath = "fast-framework/fast-generator/src/main/resources/";
    static String pomPath = "fast-framework/fast-generator\\pom.xml";
    static String module = "";

    public static void main(String[] args) throws Exception  {
        // 读取需要生成代码的xml路径
        String generatorPath = getGeneratorPath();
        // 获取模块名
        getModelName(generatorPath);
        // 生成文件目录路径
        genFilePath();
        // 读取xml文件中的table节点，获取表名和domain实体名
        Document document = new SAXReader().read("fast-framework/fast-generator/" + generatorPath);
        Node table = document.selectSingleNode("//table");
        System.out.println("读取table：" + table);
        Node tableName = table.selectSingleNode("@tableName");
        Node domainObjectName = table.selectSingleNode("@domainObjectName");
        System.out.println("tableName：" + tableName.getText() + "；domainObjectName：" + domainObjectName.getText());
        // 为DbUtil设置数据源
        Node connectionURL = document.selectSingleNode("//@connectionURL");
        Node userId = document.selectSingleNode("//@userId");
        Node password = document.selectSingleNode("//@password");
        System.out.println("读取到数据库url: " + connectionURL.getText());
        System.out.println("读取到数据库user: " + userId.getText());
        System.out.println("读取到数据库password: " + password.getText());
        DbUtil.url = connectionURL.getText();
        DbUtil.user = userId.getText();
        DbUtil.password = password.getText();
        // 示例：表名 ljx_test
        // Domain = LjxTest
        String Domain = domainObjectName.getText();
        // domain = ljxTest
        String domain = Domain.substring(0, 1).toLowerCase() + Domain.substring(1);
        // do_main = ljx-test
        String do_main = tableName.getText().replaceAll("_", "-");
        // 表中文名
        String tableNameCn = DbUtil.getTableComment(tableName.getText());
        // 表所有的字段
        List<Field> fieldList = DbUtil.getColumnByTableName(tableName.getText());
        Set<String> typeSet = getJavaTypes(fieldList);

        // 组装参数
        Map<String, Object> param = new HashMap<>();
        param.put("module", module);
        param.put("Domain", Domain);
        param.put("domain", domain);
        param.put("do_main", do_main);
        param.put("tableNameCn", tableNameCn);
        param.put("fieldList", fieldList);
        param.put("typeSet", typeSet);
        param.put("tableName", tableName.getText());
//        param.put("readOnly", readOnly);
        System.out.println("组装参数：" + param);

        gen(Domain, param, "serviceImpl", "service/impl");
        gen(Domain, param, "controller", "controller");
        gen(Domain, param, "dao", "dao");
        gen(Domain, param, "mapper", "mapper");
        gen(Domain, param, "entity", "domain/entity");
        gen(Domain, param, "service", "service");
        genXml(Domain, param, "mapperXml", "mapper");
    }

    /**
     * 生成xml文件
     * @param Domain
     * @param param
     * @param target
     * @param packageName
     */
    private static void genXml(String Domain, Map<String, Object> param, String target, String packageName) {
        try {
            FreemarkerUtil.initConfig(target + ".ftl");
            // 最终的文件路径
            String toPath = resourcesPath + packageName + "/";
            new File(toPath).mkdirs();
            String filename = toPath + Domain  + "Mapper.xml";
            System.out.println("生成文件路径：" + filename);
            FreemarkerUtil.generator(filename, param);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取所有的Java类型，使用Set去重
     * @param fieldList
     * @return
     */
    private static Set<String> getJavaTypes(List<Field> fieldList) {
        Set<String> set = new HashSet<>();
        for (int i = 0; i < fieldList.size(); i++) {
            Field field = fieldList.get(i);
            set.add(field.getJavaType());
        }
        return set;
    }

    private static void genFilePath() {
        serverPath = serverPath.replace("[module]", module);
        resourcesPath = resourcesPath.replace("[module]", module);
        new File(serverPath).mkdirs();
        System.out.println("最终生成文件的路径：" + serverPath);
    }

    /**
     * 获取模块名
     * @param generatorPath
     */
    private static void getModelName(String generatorPath) {
        // 比如src/main/resources/generator-config-user.xml，得到module = member
        module = generatorPath.replace("src/main/resources/generator-config-", "").replace(".xml", "");
        System.out.println("模块名: " + module);
    }



    /**
     * 读取需要生成代码的xml路径
     * @return
     * @throws DocumentException
     */
    private static String getGeneratorPath() throws DocumentException {
        // 读取pom.xml文件
        SAXReader saxReader = new SAXReader();
        Map<String, String> map = new HashMap<>();
        map.put("pom", "http://maven.apache.org/POM/4.0.0");
        saxReader.getDocumentFactory().setXPathNamespaceURIs(map);
        Document document = saxReader.read(pomPath);
        // 找到<configurationFile>标签，读取内容
        Node node = document.selectSingleNode("//pom:configurationFile");
        System.out.println("读取的xml文件路径：" + node.getText());
        return node.getText();
    }

    /**
     * 生成代码
     * @param Domain
     * @param param
     * @param target
     * @param packageName
     */
    private static void gen(String Domain, Map<String, Object> param, String target, String packageName) {
        try {
            FreemarkerUtil.initConfig(target + ".ftl");
            // target首字母大写
            String Target = target.substring(0, 1).toUpperCase() + target.substring(1);
            // 最终的文件路径
            String toPath = serverPath + packageName + "/";
            new File(toPath).mkdirs();
            String filename = toPath + Domain + Target + ".java";
            System.out.println("生成文件路径：" + filename);
            FreemarkerUtil.generator(filename, param);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
